package vue;

import java.awt.BorderLayout;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import util.PluginMenuItemBuilder;
import visu.Dessinable;
import bebetes.BebeteAbstraite;
import bebetes.ChampDeBebetes;
import bebetes.ChampDeBebetesAunChampi;
import bebetes.Champi;
import bebetes.Comportement;
import bebetes.FabriqueEntites;
import bebetes.FabriquePlugins;

/**
 * Cette classe implemente une interface graphique permet
 * de tester le principe des Plugins et du chargement dynamique de classes
 *
 */
public class InterfaceGraphique{
	  final JFrame f = new JFrame();
	  private FabriquePlugins pluginFactory;
	  private int largeur = 640;
	  private int hauteur = 480;

	  private PluginMenuItemBuilder champiMenuBuilder;
	  private JMenuBar mb = new JMenuBar();
	  
	  private ChampDeBebetes champ;
	  int nombreDeBebete;
	  int nombreDeChampi;
	  ArrayList<Dessinable> listeDessinable = new ArrayList<Dessinable>();
	  private List<BebeteAbstraite> predateur = new ArrayList<BebeteAbstraite>();
	  private static Logger logger = Logger.getLogger("main.TestSimulation");
	  

	  public InterfaceGraphique(int nbBebetes, int nbChampi, int delaisSimu) {
		nombreDeBebete = nbBebetes;
		nombreDeChampi = nbChampi;
	    f.setTitle("Lancement de bebetes avec plugins");
	    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		FabriqueEntites.init(FabriquePlugins.class);
		pluginFactory = (FabriquePlugins)FabriqueEntites.getFabriqueEntites();
	    ajouterMenuPlugin();
	    champ = pluginFactory.creeChampDeBebetes(largeur,hauteur,nombreDeBebete);
	    champ.setDelaiSimulation(delaisSimu);
	    /*
	     * ajout du nombre de bebete choisi
	     */
	    int i = 0;
	    while(i < champ.getListBebetes().size())
	    {
	    	listeDessinable.add(champ.getListBebetes().get(i));
	    	if(champ.getListBebetes().get(i).getComportementPredateur() != null);
	    		predateur.add(champ.getListBebetes().get(i));
	    	i++;
	    }
	    /*
	     * ajout du nombre de champi choisi
	     */
	    i = 1;
	    while(i < nombreDeChampi)
	    {
	    	if(champ instanceof ChampDeBebetesAunChampi)
	    	{
	    		((ChampDeBebetesAunChampi) champ).ajouterChampi();
	    		List<Champi> listeChampi = ((ChampDeBebetesAunChampi) champ).getListeChampis();
	    		listeDessinable.add(listeChampi.get(listeChampi.size() - 1));
		    	
	    	}
	    	champ.setDessinables(listeDessinable);
	    	i++;
	    }
	    f.getContentPane().add(champ, BorderLayout.CENTER);
	    f.pack();

	    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
	    int largeurEcran = screenSize.width;
	    int hauteurEcran = screenSize.height;
	    int largeurFrame = f.getSize().width;
	    int hauteurFrame = f.getSize().height;
	    int posX = (largeurEcran - largeurFrame) / 2;
	    int posY = (hauteurEcran - hauteurFrame) / 2;
	    f.setLocation(posX, posY);

	    // demarrage de la simulation
	    champ.demarre();
	    f.setVisible(true);
	  }

	  /*
	   * Ajout des boutons de simulation
	   * On peut redemarer, mettre en pause (et reprendre)
	   * ouvrir le panneau de controle,
	   * celui de test, et quitter
	   */
	  private void ajouterMenuSimulation()
	  {
		JMenu simulation = new JMenu("Simulation");
		JMenuItem redemarrer = new JMenuItem("Redemarrer");
		redemarrer.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		      champ.arrete();
		      champ.removeAll();
		      champ.initialiseElements();
		      champ.demarre();
		    }
		  });
		final JMenuItem pause = new JMenuItem("Pause");
		final JMenuItem reprise = new JMenuItem("Reprise");
		reprise.setEnabled(false);
		pause.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		      champ.arrete();
		      reprise.setEnabled(true);
		      pause.setEnabled(false);
		    }
		  });
		reprise.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		      champ.demarre();
		      pause.setEnabled(true);
		      reprise.setEnabled(false);
		    }
		  });
		JMenuItem panneauControle = new JMenuItem("Panneau de controle");
		panneauControle.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
				BoiteControle panneau = new BoiteControle(champ.getSimulateur(), predateur, champ.getNombreDeBebetes());
		    }
		  });
		JMenuItem panneauConsole = new JMenuItem("Console de test");
		panneauConsole.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
				Console console = new Console();
				console.setVisible(true);
				}
		  });
		  
		JMenuItem quitter = new JMenuItem("Quitter");
		quitter.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		      System.exit(0);
		    }
		  });
		simulation.add(redemarrer);
		simulation.add(pause);
		simulation.add(reprise);
		simulation.add(panneauControle);
		simulation.add(panneauConsole);
		simulation.add(quitter);
		mb.add(simulation);
	  }
	  
	  /*
	   * Gere le menu pour charger et recharger les plugins
	   */
	  private void ajouterMenuChargement()
	  {
		JMenu gererPlugins = new JMenu("Gerer plugins");
	    JMenuItem charger = new JMenuItem("Charger des nouveaux plugins");
	    charger.addActionListener(new ActionListener() {
	      public void actionPerformed(ActionEvent e) {
	        pluginFactory.loadPlugins();
	        ajouterMenuPlugin();
	      }
	    });
	    JMenuItem recharger = new JMenuItem("Recharger les plugins");
	    recharger.addActionListener(new ActionListener() {
	      public void actionPerformed(ActionEvent e) {
	        pluginFactory.reloadPlugins();
	        ajouterMenuPlugin();
	      }
	    });
		gererPlugins.add(charger);
		gererPlugins.add(recharger);
		mb.add(gererPlugins);
	  }
	  
	  /*
	   * Ajout du menu avec tous les plugins
	   */
	  private void ajouterMenuPlugin()
	  {
		  mb.removeAll();
		  ajouterMenuSimulation();
		  ajouterMenuChargement();
		  JMenu ajouterPlugins = new JMenu("Ajouter plugins");
		  ActionListener listener;
	    JMenu bebeteMenu = new JMenu("Bebete");
	    Comportement[] compNormaux = pluginFactory.getComportementNormaux();
	    int i = 0;
	    while(i < compNormaux.length)
	    {
	    	final JMenuItem courant = new JMenuItem(compNormaux[i].getClass().getName());
	    	courant.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent a) {
			        logger.info("set comportement #" + pluginFactory.getBebeteIdx());
			        Random rand = new Random();
			        Comportement compNormal = pluginFactory.getComportementNormaux()[0];
			        int i = 0;
			        while(i < pluginFactory.getComportementNormaux().length)
			        {
			        	if(pluginFactory.getComportementNormaux()[i].getName().equals(courant.getText().substring(8)))
			        	{
			        		compNormal = pluginFactory.getComportementNormaux()[i];
			        	}
			        	i++;
			        }

			        JOptionPane choixCompPredateur = new JOptionPane();
			        String[] nomComportement = new String[FabriquePlugins.getFabriqueEntites().getComportementPredateurs().length + 1];
					i = 1;
					nomComportement[0] = "Pas de comportement";
					while(i < FabriquePlugins.getFabriqueEntites().getComportementPredateurs().length + 1)
					{
						nomComportement[i] = FabriquePlugins.getFabriqueEntites().getComportementPredateurs()[i-1].getName();
						i++;
					}
					String compChoisi = (String) choixCompPredateur.showInputDialog(f, "Creation d'une bebete","Choisissez votre second comportement", JOptionPane.QUESTION_MESSAGE, null, nomComportement, "Pas de comportement");
					String nombreChoisi = (String) choixCompPredateur.showInputDialog(f, "Creation d'une bebete","Choisissez le nombre de bebete a creer", JOptionPane.QUESTION_MESSAGE, null, null, "1");
					
					Comportement comportementPredateur = null;
					if(compChoisi != "Pas de comportement")
					{
						i = 0;
						while(i < FabriquePlugins.getFabriqueEntites().getComportementPredateurs().length)
						{
							if(FabriquePlugins.getFabriqueEntites().getComportementPredateurs()[i].getName() == compChoisi)
								comportementPredateur = FabriquePlugins.getFabriqueEntites().getComportementPredateurs()[i];
							i++;
						}
						
					}
					i = 0;
					int nombreComportement = 1;
					if(nombreChoisi != null)
					{
						try
						{
							nombreComportement = Integer.parseInt(nombreChoisi);
						}
						catch(NumberFormatException n){}
					}
					while(i < nombreComportement)
					{
						BebeteAbstraite b = pluginFactory.creeBebete(champ, rand.nextInt(largeur), rand.nextInt(hauteur), rand.nextInt(10), rand.nextInt(10), new Color(Math.abs(rand.nextInt()) % 256, Math.abs(rand.nextInt()) % 256, Math.abs(rand.nextInt()) % 256), compNormal, comportementPredateur);
						listeDessinable.add(b);
						predateur.add(b);
						champ.setNombreDeBebetes(++nombreDeBebete);
				        champ.setDessinables(listeDessinable);
				        i++;
					}
				}
			});
	    	bebeteMenu.add(courant);
	    	i++;
	    }
	    ajouterPlugins.add(bebeteMenu);
		
		 listener = new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		        // Met le plugin selectionne numeroo X dans le menu comme champi
		        // courant. Le numero est contenu dans ActionCommand()
		    	pluginFactory.setChampiIdx(Integer.parseInt(
		            ( (JMenuItem) e.getSource()).getActionCommand()));
		    	if(champ instanceof ChampDeBebetesAunChampi)
		    	{
		    		((ChampDeBebetesAunChampi) champ).ajouterChampi();
		    		List<Champi> listeChampi = ((ChampDeBebetesAunChampi) champ).getListeChampis();
		    		listeDessinable.add(listeChampi.get(listeChampi.size() - 1));
			    	
		    	}
		    	champ.setDessinables(listeDessinable);
		    	
		      }
		    }; 
		    //if (champiMenuBuilder == null) {
		      champiMenuBuilder = new PluginMenuItemBuilder(pluginFactory.getChampiConstructors(),
		          listener);
		      champiMenuBuilder.setMenuTitle("Champis");
		    //}
		    champiMenuBuilder.buildMenu();
		    ajouterPlugins.add(champiMenuBuilder.getMenu());
		    mb.add(ajouterPlugins);
		    f.setJMenuBar(mb);
	  }
}

